package com.ruicar.afs.cloud.workflow.greatwall.processor.impl.objcode;

import cn.hutool.core.thread.ThreadUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.dynamicrequest.DynamicRequest;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.AfsFlowQueryRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.request.TaskCreateRequest;
import com.ruicar.afs.cloud.workflow.api.dto.afsprocess.response.TaskCreateResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FlowInstanceBean;
import com.ruicar.afs.cloud.workflow.api.enums.FlowStatus;
import com.ruicar.afs.cloud.workflow.api.util.FlowMappingHelper;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtFlowEngineResponse;
import com.ruicar.afs.cloud.workflow.greatwall.dto.GwtRequest;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallTaskInfo;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowBizData;
import com.ruicar.afs.cloud.workflow.greatwall.entity.AfsGreatWallWorkflowMappingInfo;
import com.ruicar.afs.cloud.workflow.greatwall.enums.GwtMsgType;
import com.ruicar.afs.cloud.workflow.greatwall.enums.GwtObjectCode;
import com.ruicar.afs.cloud.workflow.greatwall.enums.RequestPath;
import com.ruicar.afs.cloud.workflow.greatwall.feign.GwtWorkFLowFeign;
import com.ruicar.afs.cloud.workflow.greatwall.mapper.AfsGreatWallTaskInfoMapper;
import com.ruicar.afs.cloud.workflow.greatwall.processor.GwfObjectCodeProcessor;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowBizDataService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowMappingInfoService;
import com.ruicar.afs.cloud.workflow.greatwall.service.AfsGreatWallWorkflowNoticeExceptionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;

import static com.ruicar.afs.cloud.workflow.api.constant.FlowConstant.FLOW_EXCEPTION_DESC_KEY;

/**
 * The type TaskCreateNoticeProcessor
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date Created on 2020.07.10 21:22:46
 * @since 1.0
 */
@Component
@Slf4j
public class TaskCreateNoticeProcessor extends AbsGwfNoticeProcessor implements GwfObjectCodeProcessor {
    /**
     * Afs great wall workflow mapping info service
     * <p>Description: </p>
     */
    private final AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService;
    /**
     * Dynamic request
     * <p>Description: </p>
     */
    private final DynamicRequest dynamicRequest;

    private final GwtWorkFLowFeign fLowFeign;


    private final AfsGreatWallTaskInfoMapper afsGreatWallTaskInfoMapper;

    public TaskCreateNoticeProcessor(AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService, AfsGreatWallWorkflowNoticeExceptionService afsGreatWallWorkflowNoticeExceptionService, AfsGreatWallWorkflowMappingInfoService afsGreatWallWorkflowMappingInfoService, DynamicRequest dynamicRequest, GwtWorkFLowFeign fLowFeign, AfsGreatWallTaskInfoMapper afsGreatWallTaskInfoMapper) {
        super(afsGreatWallWorkflowBizDataService, afsGreatWallWorkflowNoticeExceptionService);
        this.afsGreatWallWorkflowMappingInfoService = afsGreatWallWorkflowMappingInfoService;
        this.dynamicRequest = dynamicRequest;
        this.fLowFeign = fLowFeign;
        this.afsGreatWallTaskInfoMapper = afsGreatWallTaskInfoMapper;
    }

    /**
     * Process key string
     *
     * @return the string
     */
    @Override
    public String processKey() {
        return MessageFormat.format("{0}-{1}", AfsEnumUtil.key(belongMsg()), AfsEnumUtil.key(objectCode()));
    }

    /**
     * Belong msg gwt msg type
     *
     * @return the gwt msg type
     */
    @Override
    public GwtMsgType belongMsg() {
        return GwtMsgType.PUSH_DATA;
    }

    /**
     * Object code gwt object code
     *
     * @return the gwt object code
     */
    @Override
    public GwtObjectCode objectCode() {
        return GwtObjectCode.TASK_CREATE;
    }


    private void saveError(GwtRequest request, AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData) {
        if (afsGreatWallWorkflowBizData != null) {
            TaskCreateRequest taskCreateRequest = JSON.parseObject(request.getBody(), TaskCreateRequest.class);
            saveException(request, afsGreatWallWorkflowBizData.getFlowInstanceId(), (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), taskCreateRequest.getNodeId()))));
            afsGreatWallWorkflowBizData.setFlowStatus(FlowStatus.ERROR);
            String bizData="{}";
            if(StringUtils.isNotEmpty(afsGreatWallWorkflowBizData.getBizData())){
                bizData = afsGreatWallWorkflowBizData.getBizData();
            }
            JSONObject bizDataJson = JSONObject.parseObject(bizData);
            bizDataJson.put(FLOW_EXCEPTION_DESC_KEY,"业务端保存节点信息异常");
            afsGreatWallWorkflowBizData.setBizData(bizDataJson.toJSONString());
            afsGreatWallWorkflowBizDataService.updateById(afsGreatWallWorkflowBizData);
        }
    }

    /**
     * Process string
     *
     * @param request request
     * @return the string
     */
    @Override
    public String process(GwtRequest request) {
        log.info("任务创建通知{}", request);
        TaskCreateRequest taskCreateRequest = JSON.parseObject(request.getBody(), TaskCreateRequest.class);
        taskCreateRequest.setAfsFlowKey(FlowMappingHelper.getAfsKey(request.getServiceId()));
        taskCreateRequest.setServiceId(request.getServiceId());
        taskCreateRequest.setDataId(request.getDataId());
        taskCreateRequest.setBizDataId(request.getDataId());
        AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData = afsGreatWallWorkflowBizDataService.getBizDataObjServiceIdAndDataId(request.getServiceId(), request.getDataId());
        if (afsGreatWallWorkflowBizData != null) {
            afsGreatWallWorkflowBizData.setFlowInstanceId(taskCreateRequest.getFlowInstanceId());
            afsGreatWallWorkflowBizDataService.updateById(afsGreatWallWorkflowBizData);
        }
        if (afsGreatWallWorkflowBizDataService.exception(request.getServiceId(), request.getDataId())) {
            if (afsGreatWallWorkflowBizData != null) {
                saveException(request, afsGreatWallWorkflowBizData.getFlowInstanceId(), (genExceptionCheckCode(MessageFormat.format("{0}-{1}-{2}", request.getServiceId(), request.getDataId(), taskCreateRequest.getNodeId()))));
            }
            ThreadUtil.execute(new SaveFlowNode(request.getServiceId(), request.getDataId(), afsGreatWallTaskInfoMapper, taskCreateRequest));
            return bizError;
        }

        AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo = afsGreatWallWorkflowMappingInfoService.queryMappingByServiceId(request.getServiceId());
        TaskCreateResponse taskCreateResponse = new TaskCreateResponse();
        try {
            if (afsGreatWallWorkflowMappingInfo != null) {
                if (noticeBiz(request, afsGreatWallWorkflowMappingInfo, false)) {
                    taskCreateResponse.setSuccess(true);
                } else {
                    taskCreateResponse.setSuccess(false);
                    //未拿到实例编号数据不做处理
                    if (afsGreatWallWorkflowBizData != null && StringUtils.isNotEmpty(afsGreatWallWorkflowBizData.getFlowInstanceId())) {
                        saveError(request, afsGreatWallWorkflowBizData);
                    }
                }
            } else {
                throw new AfsBaseException("通知数据失败");
            }
        } catch (Exception e) {
            saveError(request, afsGreatWallWorkflowBizData);
            throw e;
        }
        return JSONObject.toJSONString(taskCreateResponse);
    }


    @Override
    public boolean processError(GwtRequest request) {
        AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo = afsGreatWallWorkflowMappingInfoService.queryMappingByServiceId(request.getServiceId());
        if (afsGreatWallWorkflowMappingInfo != null) {
            try {
                return noticeBiz(request, afsGreatWallWorkflowMappingInfo, true);
            } catch (Exception e) {
                return false;
            }
        } else {
            return false;
        }
    }

    private boolean noticeBiz(GwtRequest request, AfsGreatWallWorkflowMappingInfo afsGreatWallWorkflowMappingInfo, boolean error) {
        try {
            TaskCreateRequest taskCreateRequest = JSON.parseObject(request.getBody(), TaskCreateRequest.class);
            AfsFlowQueryRequest<TaskCreateRequest> afsFlowQueryRequest = new AfsFlowQueryRequest<>();
            afsFlowQueryRequest.setAfsFlowKey(afsGreatWallWorkflowMappingInfo.getAfsFlowKey());
            afsFlowQueryRequest.setData(taskCreateRequest);
            taskCreateRequest.setAfsFlowKey(afsFlowQueryRequest.getAfsFlowKey());
            taskCreateRequest.setServiceId(request.getServiceId());
            taskCreateRequest.setDataId(request.getDataId());
            taskCreateRequest.setBizDataId(request.getDataId());
            long taskCount = afsGreatWallTaskInfoMapper.selectCount(Wrappers.<AfsGreatWallTaskInfo>lambdaQuery().eq(AfsGreatWallTaskInfo::getFlowServiceId, request.getServiceId()).eq(AfsGreatWallTaskInfo::getBizDataId, request.getDataId()));
            if (!error) {
                ThreadUtil.execute(new SaveFlowNode(request.getServiceId(), request.getDataId(), afsGreatWallTaskInfoMapper, taskCreateRequest));
            }
            //首节点不推送
            if (taskCount > 0) {
                IResponse<TaskCreateResponse> response = dynamicRequest.post(afsGreatWallWorkflowMappingInfo.getServiceName(), AfsEnumUtil.key(RequestPath.TASK_CREATE), afsFlowQueryRequest, new TypeReference<TaskCreateResponse>() {
                });
                if (CommonConstants.SUCCESS.equalsIgnoreCase(response.getCode()) && response.getData().isSuccess()) {
                    ThreadUtil.execute(new FinishFlowInstance(request.getServiceId(), request.getDataId(), afsGreatWallWorkflowBizDataService,taskCreateRequest.getStatus()));
                    return true;
                }
            } else {
                return true;
            }
            return false;
        } catch (Exception e) {
            log.error("", e);
            throw e;
        }
    }

    @Slf4j
    private static class FinishFlowInstance implements Runnable {
        private final String serviceId;
        private final String bizDataId;
        private final String status;
        private final AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService;
        public FinishFlowInstance(String serviceId, String bizDataId, AfsGreatWallWorkflowBizDataService afsGreatWallWorkflowBizDataService,String status) {
            this.serviceId = serviceId;
            this.bizDataId = bizDataId;
            this.afsGreatWallWorkflowBizDataService = afsGreatWallWorkflowBizDataService;
            this.status = status;
        }

        @Override
        public void run() {
            log.info("检测serviceId={},bizDataId={}的流程是否完成", this.serviceId, this.bizDataId);
            AfsGreatWallWorkflowBizData afsGreatWallWorkflowBizData = afsGreatWallWorkflowBizDataService.getBizDataObjServiceIdAndDataId(serviceId, bizDataId);
            if (afsGreatWallWorkflowBizData != null && StringUtils.isNotEmpty(afsGreatWallWorkflowBizData.getFlowServiceId())&&StringUtils.equals("2",status)) {
                afsGreatWallWorkflowBizDataService.setFinish(afsGreatWallWorkflowBizData.getId());
            }
        }
    }

    @Slf4j
    private static class SaveFlowNode implements Runnable {
        private final String serviceId;
        private final String bizDataId;
        private final AfsGreatWallTaskInfoMapper afsGreatWallTaskInfoMapper;
        private final TaskCreateRequest taskCreateRequest;

        public SaveFlowNode(String serviceId, String bizDataId, AfsGreatWallTaskInfoMapper afsGreatWallTaskInfoMapper, TaskCreateRequest taskCreateRequest) {
            this.serviceId = serviceId;
            this.bizDataId = bizDataId;
            this.afsGreatWallTaskInfoMapper = afsGreatWallTaskInfoMapper;
            this.taskCreateRequest = taskCreateRequest;
        }

        @Override
        public void run() {
            log.info("保存任务信息{},{}", this.serviceId, this.bizDataId);
            AfsGreatWallTaskInfo afsGreatWallTaskInfo = new AfsGreatWallTaskInfo();
            afsGreatWallTaskInfo.setAfsFlowKey(taskCreateRequest.getAfsFlowKey());
            afsGreatWallTaskInfo.setFlowInstanceId(taskCreateRequest.getFlowInstanceId());
            afsGreatWallTaskInfo.setBizDataId(bizDataId);
            afsGreatWallTaskInfo.setFlowServiceId(serviceId);
            afsGreatWallTaskInfo.setNodeName(taskCreateRequest.getTaskName());
            afsGreatWallTaskInfo.setFlowName(taskCreateRequest.getFlowName());
            afsGreatWallTaskInfo.setNodeId(taskCreateRequest.getNodeId());
            afsGreatWallTaskInfoMapper.insert(afsGreatWallTaskInfo);
        }
    }
}
